#ifndef QUEUE_CORE_H_
#define QUEUE_CORE_H_

#include "Chain.hh"
#include "Lock.hh"
#include "Signal.hh"

//
/**
 * \file QueueCore.hh
 * \author  jsk <jsk.jinsubkim@gmail.com>
 * \version 1.0
 *
 * \class QueueCore QueueCore.hh
 *
 * Thread safe한 큐를 구현한다.
 * 
 * 큐를 구현하기 위해서 
 */
class QueueCore
{
public:
	/**
	 * \name QueueCore
	 * \param Key 큐의 입출력을 보호할 락.
	 * \param EmptyEvent 큐가 비워졌을 때를 알리는 이벤트.
	 * \param List 데이터 관리를 위해서 사용할 리스트.
	 */
	QueueCore(Signal* EmptyEvent, Chain* List);
	
	/**
	 * \name enqueue
	 * \param Data 삽입되는 데이터.
	 * 
	 * 큐에 데이터를 삽입한다.
	 * 
	 * 리스트에 데이터를 삽입한다. 이 과정은 락을 통해서 보호된다.
	 * 데이터가 큐에 삽입되었음을 알린다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf enqueue(void* Data);
	
	/**
	 * \name dequeue
	 * 
	 * 큐에서 데이터를 반환한다.
	 * 
	 * 리스트에서 가장 오래된 데이터를 가져오고, 그 데이터를 반환한다.
	 * 만약  waitEmpty 메소드가 호출된 후에, 큐의 크기가 0일 경우 
	 * 큐가 비워졌다는 신호를 발생시킨다.
	 * 
	 * \return 
	 * 
	 * 데이터가 있을 경우 데이터의 주소를 반환하고, 
	 * 큐가 종료하거나 에러가 발생할 경우 NULL을 반환한다.
	 */
	virtual void* dequeue();
	
	/**
	 * \name fill
	 * 
	 * flush 메소드는 큐를 비우기위해서 enqueue를 불가능하도록 한다.
	 * 다시 enqueue를 하기 위해서 fill 메소드를 사용한다.
	 * 
	 * 큐를 다시 삽입할 수 있도록 만든다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf fill();
	
	/**
	 * \name flush
	 * 
	 * 큐를 비운다.
	 * 
	 * 큐에 새로운 데이터를 삽입하는 것을 불가능하게 한 후에 큐의 크기가 0이면 
	 * 바로 종료하고,큐의 크기가 0보다 클 경우에 큐가 비워졌다는 신호를 기다린다.
	 * 
	 * \warning
	 * 
	 * 큐가 비워질 때까지 새로운 데이터가 입력되는 것이 불가능해 진다.
	 * 
	 * \return 
	 * 
	 * 성공할 경우 RETURN_OK, 
	 * 실패할 경우 RETURN_OK가 아닌 값.
	 */
	virtual ResultOf flush();
	
	/**
	 * \name tellsSize
	 * 
	 * 큐의 크기를 알려준다.
	 * 
	 * \return 
	 * 
	 * 큐에 저장된 데이터의 개수.
	 */
	virtual USNumber tellSize();
	
	// Mmember
protected:
	/**
	 * 데이터 삽입 - push 메소드 - 기능을 비활성화 시킨다.
	 */
	bool DisablePush;
	
	/**
	 * 큐가 비워졌음을 알리는 시그널.
	 */
	Signal* SignalOfEmptyEvent;
	
	/**
	 * 리스트.
	 */
	Chain* ListOfObject;
	
	/**
	 * 인스턴스의 상태를 나타낸다.
	 * TRUE일 경우 정상, FALSE일 경우 비정상.
	 */
	bool State;
};

#define __sync_synchronize() __sync_synchronize()

#endif //QUEUE_CORE_H_